# config_page.py
from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtWidgets import *
from pathlib import Path
from ui.config_ui import Ui_Dialog
from sql.model import DatabaseModel
import json


class ConfigPage:
    def __init__(self, ui_section):
        self.ui = ui_section
        self.tree_manager = TreeManager(self.ui)
        self.file_preprocess_manager = None  # 新增
        self._is_initialized = False
        self.config_dir = Path('configs')  # 配置目录路径

    def on_page_show(self):
        """当页面显示时初始化（带延迟）"""
        if not self._is_initialized:
            QTimer.singleShot(100, self._delayed_init)  # 延迟100ms
            self._is_initialized = True
    
    def _delayed_init(self):  # 新增方法
        """延迟初始化所有组件"""
        self.tree_manager.init_tree()
        
        # 初始化文件预处理管理器
        if file_preprocess_ui := self.ui.findChild(QWidget, "file_preprocess"):
            self.file_preprocess_manager = FilePreprocessManager(file_preprocess_ui, self)
            
            # 初始化表格
            table = file_preprocess_ui.findChild(QTableWidget, "tableWidget")
            table.setColumnCount(2)
            table.setHorizontalHeaderLabels(["参数字段", "参数值"])
            table.setRowCount(1)
    
    def _show_status(self, message):
        """显示状态消息"""
        QMessageBox.information(
            self.ui,
            "操作成功",
            message,
            QMessageBox.StandardButton.Ok
        )
            
    def _show_error(self, message):
        """显示错误弹窗"""
        QMessageBox.critical(
            self.ui,
            "操作失败",
            message,
            QMessageBox.StandardButton.Ok
        )

class TreeManager(QObject):
    page_changed = Signal(str)  # 信号传递页面名称

    def __init__(self, ui):
        super().__init__()
        self.ui = ui
        self.tree = self.ui.findChild(QTreeWidget, "treeWidget")
        if not self.tree:
            raise ValueError("未找到treeWidget控件")
        self.stacked_widget = self.ui.findChild(QStackedWidget, "stackedWidget_2")
        if not self.stacked_widget:
            raise ValueError("未找到stackedWidget_2控件")
    def init_tree(self):
        """初始化树节点与页面映射"""
        self.tree.expandAll()  # 展开所有节点
        self.tree.setCurrentItem(self.tree.topLevelItem(0))  # 默认选中第一个
        self._setup_tree_items()
        self.tree.itemClicked.connect(self._handle_tree_click)
        
    def _setup_tree_items(self):
        """建立树节点与页面的映射关系"""
        nodes = {
            "日志配置": "log_config",
            "基础参数": "basic_config",
            "文件存储格式预处理": "file_preprocess",
            "文件存储": "file_storage",
            "数据库连接": "db_config",
            "API配置": "api_config",
            "图表配置": "chart_config",
            "算法配置": "algorithm_config",
            "报告配置": "report_config",
            "权限配置": "permission_config"
        }
        
        iterator = QTreeWidgetItemIterator(self.tree)
        while iterator.value():
            item = iterator.value()
            if item.text(0) in nodes:
                item.setData(0, Qt.UserRole, nodes[item.text(0)])
            iterator += 1

    def _handle_tree_click(self, item):
        """处理树节点点击事件"""
        print(f"点击的节点文本：{item.text(0)}, 关联数据：{item.data(0, Qt.UserRole)}") # 添加调试输出
        page_name = item.data(0, Qt.UserRole)
        if page_name:
            self._switch_page(page_name)
            
    def _switch_page(self, page_name):
        """切换堆叠页面"""
        page_map = {
            "log_config": 0,
            "basic_config": 1,
            "file_preprocess": 2,
            "file_storage": 3,
            "db_config": 4,
            "api_config": 5,
            "chart_config": 6,
            "algorithm_config": 7,
            "report_config": 8,
            "permission_config": 9
        }
        self.stacked_widget.setCurrentIndex(page_map[page_name])
        self.page_changed.emit(page_name)
        
        if page_name == "file_preprocess":
            if table := self.ui.findChild(QTableWidget, "tableWidget"):
                table.setEditTriggers(QTableWidget.EditTrigger.DoubleClicked)
                table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
                table.setCornerButtonEnabled(False)
                table.verticalHeader().setDefaultSectionSize(30)
                table.verticalHeader().setMinimumWidth(40)
        

        # 添加切换动画
        anim = QPropertyAnimation(self.stacked_widget, b"pos")
        anim.setDuration(300)
        anim.setEasingCurve(QEasingCurve.OutQuad)
        anim.setStartValue(QPoint(100, 0))
        anim.setEndValue(QPoint(0, 0))
        anim.start()

class FilePreprocessManager(QObject):
    def __init__(self, ui, page_instance):
        super().__init__()
        self.ui = ui
        self.page = page_instance
        self.table = self.ui.findChild(QTableWidget, "tableWidget")
        self._init_buttons()
        self._init_table()

    # 在 FilePreprocessManager 的 _init_buttons 方法中添加预览按钮连接
    def _init_buttons(self):
        """初始化按钮连接"""
        btn_names = {
            "pushButton_30": self._add_row,
            "pushButton_31": self._add_column,
            "pushButton_32": self._delete_row,
            "pushButton_33": self._delete_column,
            "pushButton_34": self._save_config,
            "pushButton_35": self._open_config_storage,
        }
        
        for btn_name, handler in btn_names.items():
            if btn := self.ui.findChild(QPushButton, btn_name):
                btn.clicked.connect(handler)
    
    def _init_table(self):
        """初始化表格属性"""
        # 设置行号列不可编辑
        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
        self.table.verticalHeader().setSectionsClickable(False)

        # 启用单元格编辑（默认已启用，此处显式设置）
        self.table.setEditTriggers(QTableWidget.DoubleClicked | QTableWidget.EditKeyPressed)

        # 设置表头为可编辑
        header = self.table.horizontalHeader()
        header.setSectionsClickable(True)
        header.sectionDoubleClicked.connect(self._edit_header)

    def _add_row(self):
        """添加新行（带行号保护）"""
        row = self.table.currentRow() + 1 if self.table.currentRow() >= 0 else self.table.rowCount()
        self.table.insertRow(row)
        
        # 自动填充可编辑单元格
        for col in range(self.table.columnCount()):
            item = QTableWidgetItem("")
            item.setFlags(item.flags() | Qt.ItemIsEditable)  # 明确设置可编辑
            self.table.setItem(row, col, item)

    def _add_column(self):
        """添加新列"""
        col = self.table.columnCount()
        self.table.insertColumn(col)
        self.table.setHorizontalHeaderItem(col, QTableWidgetItem(''))

    def _delete_row(self):
        """删除选中行"""
        if (row := self.table.currentRow()) >= 0:
            self.table.removeRow(row)

    def _delete_column(self):
        """删除选中列"""
        if (col := self.table.currentColumn()) >= 0 and self.table.columnCount() > 1:
            self.table.removeColumn(col)

    def _save_config(self):
        """保存配置到文件"""
        try:
            # 获取表头
            headers = [self.table.horizontalHeaderItem(i).text() for i in range(self.table.columnCount())]
            # 构建数据列表
            config_data = []
            for row in range(self.table.rowCount()):
                row_data = {}
                for col, header in enumerate(headers):
                    item = self.table.item(row, col)
                    row_data[header] = item.text() if item else ""
                config_data.append(row_data)

            # 保存文件
            file_path, _ = QFileDialog.getSaveFileName(
                self.ui,
                "保存预处理配置",
                "",
                "JSON Files (*.json)"
            )
            
            if file_path:
                with open(file_path, 'w', encoding='utf-8') as f:
                    json.dump(config_data, f, indent=2, ensure_ascii=False)
                
                self.page._show_status(f"配置已保存到：{file_path}")

        except Exception as e:
            self.page._show_error(f"保存失败：{str(e)}")

    def _edit_header(self, index):
        """编辑表头"""
        current_header = self.table.horizontalHeaderItem(index).text()
        new_header, ok = QInputDialog.getText(self.ui, "编辑表头", "请输入新的表头名称:", QLineEdit.Normal, current_header)
        if ok and new_header:
            self.table.setHorizontalHeaderItem(index, QTableWidgetItem(new_header))

    def _open_config_storage(self):
        """打开配置仓库对话框"""
        try:
            dialog = QDialog()
            
            dialog.setWindowIcon(QIcon(":/icon/icons/cangku.png"))
            
            ui = Ui_Dialog()
            ui.setupUi(dialog)
            dialog.setWindowTitle("配置仓库")
            self.config_storage_ui = ui

            btn_handlers = {
                ui.pushButton_2: self._preview_config,
                ui.pushButton_3: self._delete_config,
                ui.pushButton_4: self._load_config,
                ui.pushButton_5: self._new_config
            }
            for btn, handler in btn_handlers.items():
                if btn == ui.pushButton_2:
                    btn.clicked.connect(handler)
                else:
                    btn.clicked.connect(lambda _, h=handler: (h(), dialog.accept()))

            # 获取configs目录下的所有JSON文件
            config_files = list(self.page.config_dir.glob('*.json'))

            # 将配置文件添加到列表控件中
            list_widget = ui.listWidget   
            for file in config_files:
                item = QListWidgetItem(file.name)
                item.setSizeHint(QSize(100, 40))
                item.setIcon(QIcon('newProject\\icons\\file.png'))
                list_widget.addItem(item)
            
            # 保存对话框引用以便预览时使用
            self.page.config_storage_dialog = dialog

            if dialog.exec() == QDialog.Accepted:
                self.page._show_status("配置已加载")

        except Exception as e:
            self.page._show_error(f"打开配置仓库失败: {str(e)}")
    
    def _load_from_storage(self, file_path):
        """从配置仓库加载配置"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                config_data = json.load(f)
            
            self.table.setRowCount(0)
            if config_data:
                keys = config_data[0].keys()
                self.table.setColumnCount(len(keys))
                self.table.setHorizontalHeaderLabels(keys)
                
                for row, item in enumerate(config_data):
                    self.table.insertRow(row)
                    for col, key in enumerate(keys):
                        self.table.setItem(row, col, QTableWidgetItem(str(item.get(key, ""))))
        except Exception as e:
            self.page._show_error(f"加载失败：{str(e)}")

    def _load_config(self):
        """加载配置到表格控件"""
        file_path, _ = QFileDialog.getOpenFileName(
            self.ui,
            "加载配置",
            "",
            "JSON Files (*.json)"
        )
    
        if file_path:
            self._load_from_storage(file_path)  # 直接复用现有加载逻辑

    def _preview_config(self):
        """增强版配置预览"""
        try:
            # 获取当前选中的配置文件
            selected_item = self.config_storage_ui.listWidget.currentItem()
            if not selected_item:
                QMessageBox.warning(None, "提示", "请先选择要预览的配置文件")
                return

            file_path = self.page.config_dir / selected_item.text()
            
            # 创建带格式的预览对话框
            preview_dialog = QDialog()
            preview_dialog.setWindowIcon(QIcon(":/icon/icons/preview.png"))
            preview_dialog.setWindowTitle(f"配置预览 - {file_path.name}")
            preview_dialog.resize(800, 600)
            
            # 创建带行号的文本编辑器
            text_edit = QPlainTextEdit()
            text_edit.setReadOnly(True)
            text_edit.setLineWrapMode(QPlainTextEdit.NoWrap)
            
            # 设置等宽字体
            font = QFont("Consolas", 10)
            text_edit.setFont(font)
            
            # 添加搜索框
            search_box = QLineEdit()
            search_box.setPlaceholderText("输入搜索内容...")
            
            # 布局设置
            layout = QVBoxLayout()
            layout.addWidget(search_box)
            layout.addWidget(text_edit)
            preview_dialog.setLayout(layout)
            
            # 加载并高亮JSON
            with open(file_path, 'r', encoding='utf-8') as f:
                raw_data = json.load(f)
                formatted_json = json.dumps(raw_data, indent=4, ensure_ascii=False)
                
                # 语法高亮
                highlighter = JSONHighlighter(text_edit.document())
                text_edit.setPlainText(formatted_json)
            
            # 实现搜索功能
            def search_text():
                cursor = text_edit.textCursor()
                cursor.beginEditBlock()  # 新增：开始编辑块
                cursor.movePosition(QTextCursor.Start)
                
                text_edit.extraSelections = []
                search_str = search_box.text().strip()
                
                if search_str:
                    format = QTextCharFormat()
                    format.setBackground(QColor(255, 255, 0, 100))  # 修改：添加透明度
                    format.setForeground(QColor(0, 0, 0))  # 新增：设置文字颜色
                    
                    # 修改：添加搜索选项（不区分大小写）
                    flags = QTextDocument.FindCaseSensitively | QTextDocument.FindWholeWords
                    while text_edit.find(search_str, flags):
                        selection = QTextEdit.ExtraSelection()
                        selection.format = format
                        selection.cursor = text_edit.textCursor()
                        text_edit.extraSelections.append(selection)
                cursor.endEditBlock()  # 新增：结束编辑块
                text_edit.setTextCursor(cursor)  # 新增：更新光标位置
            
            search_box.textChanged.connect(search_text)
            preview_dialog.exec_()
        except Exception as e:
            self.page._show_error(f"预览失败：{str(e)}")
        
    def _delete_config(self):
        """删除配置"""
        try:
            # 获取当前选中的配置项
            list_widget = self.config_storage_ui.listWidget
            if not list_widget.currentItem():
                self.page._show_error("请先选择要删除的配置")
                return
                
            # 获取文件路径
            selected_item = list_widget.currentItem()
            file_path = self.page.config_dir / selected_item.text()
            
            # 执行文件删除
            if file_path.exists():
                file_path.unlink()
            
            # 更新列表显示
            list_widget.takeItem(list_widget.row(selected_item))
            self.page._show_status(f"已删除配置：{file_path.name}")

        except Exception as e:
            self.page._show_error(f"删除失败：{str(e)}")

    def _new_config(self):
        """新建配置"""
        self.table.clearContents()
        self.table.setRowCount(1)
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["参数字段", "参数值"])

# 新增JSON语法高亮类
class JSONHighlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super().__init__(parent)
        
        self.key_format = QTextCharFormat()
        self.key_format.setForeground(QColor(200, 40, 150))
        
        self.value_format = QTextCharFormat()
        self.value_format.setForeground(QColor(30, 130, 210))
        
        self.string_format = QTextCharFormat()
        self.string_format.setForeground(QColor(30, 170, 40))

    def highlightBlock(self, text):
        # 匹配JSON键
        key_regex = QRegularExpression(r'\"(\w+)\"\s*:')
        match_iterator = key_regex.globalMatch(text)
        while match_iterator.hasNext():
            match = match_iterator.next()
            self.setFormat(match.capturedStart(), match.capturedLength(), self.key_format)
        
        # 匹配字符串值
        string_regex = QRegularExpression(r'\"[^"]*\"')
        match_iterator = string_regex.globalMatch(text)
        while match_iterator.hasNext():
            match = match_iterator.next()
            self.setFormat(match.capturedStart(), match.capturedLength(), self.string_format)
        
        # 匹配数值
        number_regex = QRegularExpression(r'\b\d+\b')
        match_iterator = number_regex.globalMatch(text)
        while match_iterator.hasNext():
            match = match_iterator.next()
            self.setFormat(match.capturedStart(), match.capturedLength(), self.value_format)

class DBConfigManager(QObject):
    def __init__(self, ui, page_instance):
        super().__init__()
        self.ui = ui
        self.page = page_instance
        self.db_model = None  # 添加数据库模型实例
        self._init_ui_elements()
        self._init_connections()

    def _init_ui_elements(self):
        """初始化数据库配置相关UI元素"""
        self.db_table_combo = self.ui.findChild(QComboBox, 'dbtableComboBox')
        self.search_button = self.ui.findChild(QPushButton, 'search_button')
        self.host_line_edit = self.ui.findChild(QLineEdit, 'hostLineEdit')
        self.port_line_edit = self.ui.findChild(QLineEdit, 'portLineEdit')
        self.user_line_edit = self.ui.findChild(QLineEdit, 'usernameLineEdit')
        self.password_line_edit = self.ui.findChild(QLineEdit, 'passwordLineEdit')
        self.test_connection_button = self.ui.findChild(QPushButton, 'testConnectionButton')
        self.db_table_view = self.ui.findChild(QTableWidget, 'dbTableView')

    def _init_connections(self):
        """连接按钮信号"""
        self.test_connection_button.clicked.connect(self._test_connection)
        self.search_button.clicked.connect(self._search_data)

    def _test_connection(self):
        """测试数据库连接"""
        try:
            params = self.get_current_params()
            
            # 输入验证
            if not all(params.values()):
                raise ValueError("请填写完整连接参数")
                
            # 使用model中的类进行测试
            temp_model = DatabaseModel()
            if temp_model.test_connection(**params):
                self.db_model = temp_model  # 保存有效连接
                self.page._show_status("数据库连接成功！")
                self._load_tables()  # 连接成功后加载表
                return True
            
        except Exception as e:
            self.page._show_error(f"数据库连接失败：{str(e)}")
            return False
        
    def get_current_params(self):
        """获取当前配置参数"""
        return{
            "host": self.host_line_edit.text().strip(),
            "port": self.port_line_edit.text().strip() or "3306",  # 默认端口
            "user": self.user_line_edit.text().strip(),
            "password": self.password_line_edit.text().strip()
        }
    
    def _load_tables(self):
        """加载数据库表到下拉框"""
        try:
            tables = self.db_model.get_tables()
            self.db_table_combo.clear()
            for table in tables:
                table_name = list(table.values())[0]  # 提取表名
                self.db_table_combo.addItem(table_name)
        except Exception as e:
            self.page._show_error(f"加载表失败：{str(e)}")

    def _display_data(self, data):
        """在表格中显示数据"""
        # 需要根据你的tableView控件实现具体显示逻辑
        pass